<?php
/**
 * Работа с событиями
 * 
 * Класс для работы с событиями
 * @author Anton Zavidov
 * @package myLiveShop
 */

/**
 * Класс для работы с событиями
 *
 */
class Event extends Base {
	/**
	 * список событий и их обработчиков
	 *
	 * @var array
	 */
	private static $list;
	/**
	 * Констуктор
	 *
	 * @param string $className имя подели
	 */
	public function __construct($className=null){

		parent::__construct($className?$className:__CLASS__);
	}
	/**
	 * выполняем event
	 *
	 * @param strring $event_name имя события
	 * @param mixed $params параметры
	 * @return boolean вернёт false если хоть одна из функций его вернёт
	 */
	public static function _($event_name, $params=false){
		if(!isset(self::$list[$event_name])){
			new CoreExeption('Попытка вызвать несуществующий эвент '.$event_name,E_NOTICE,__FILE__,__LINE__);
			return null;
		}
		L('Вызван event '.$event_name);
		$return=true;
		//проходимся по всем прицепленным событиям
		foreach (self::$list[$event_name] as $key=>$item) {
			$class_name=$item['class'];
			$function_name=$item['function'];
			//проверка на возможность вызова
			if(!is_callable(array($class_name,$function_name))){
				new CoreExeption('Попытка вызвать несуществующий обработчик '.$class_name.'::'.$function_name.' эвента '.$event_name,E_WARNING,__FILE__,__LINE__);
				continue;
			}else{
				//сам вызов
				L('Вызван event '.$event_name.' для '.$class_name.'::'.$function_name);
				if(!call_user_func(array($class_name,$function_name),$params))$return=false;
			}
			//если установлен флаг once удаляем вызов
			if($item['once']){
				self::delete($event_name,$key);
			}
		}
		return $return;
	}
	/**
	 * Добавление слушателя событий
	 *
	 * @param string $event_name имя события
	 * @param string $class_name имя класса
	 * @param string $function_name имя метода в классе
	 * @param boolean $once срабатывать только один раз
	 * @return int номер под которым сохранился евент в стеке
	 */
	public static function add($event_name,$class_name,$function_name,$once=false){
		if(!is_callable(array($class_name,$function_name))){
			new CoreExeption('Попытка привязать эвент '.$event_name.' к несуществующему обработчику '.$class_name.'::'.$function_name,E_WARNING,__FILE__,__LINE__);
			return false;
		}
		if(!isset(self::$list[$event_name]))self::$list[$event_name]=array();
		self::$list[$event_name][]=array(
		"class"=>$class_name,
		"function"=>$function_name,
		"once"=>$once
		);
		L('Создан event '.$event_name.' -> '.$class_name."::".$function_name);
		return count(self::$list[$event_name])-1;
	}
	/**
	 * удаляем вызов эвента
	 *
	 * @param string $name имя евента
	 * @return boolean true если операция была успешной
	 */
	public static function delete($event_name,$param=false){
		if(!isset(self::$list[$event_name])){
			new CoreExeption('Попытка удалить несуществующий эвент '.$event_name,E_WARNING,__FILE__,__LINE__);
			return false;
		}
		if(is_int($param)){
			if(!isset(self::$list[$event_name][$param])){
				new CoreExeption('Попытка удалить несуществующую запись '.$param.' в эвенте '.$event_name,E_WARNING,__FILE__,__LINE__,array("event"=>print_r(self::$list[$event_name],true)));
				return false;
			}
			unset(self::$list[$event_name][$param]);
			return true;
		}
		if(is_string($param)){
			if(strpos($param,"::")>-1){
				$param=explode("::",$param);
				if($event=self::findEvent($event_name,$param[0],$param[1])){
					L('Удалён event '.$event_name.'('.($event-1).') -> '.$param[0]."::".$param[1]);
					unset(self::$list[$event_name][$event-1]);
					return true;
				}
				new CoreExeption('Попытка удалить несуществующую запись '.$param[0]."::".$param[1].' в эвенте '.$event_name,E_WARNING,__FILE__,__LINE__,array("event"=>self::$list[$event_name]));
				return false;
			}
			new CoreExeption('Попытка удалить несуществующую запись '.$param.' в эвенте '.$event_name,E_WARNING,__FILE__,__LINE__,array("event"=>self::$list[$event_name]));
			return false;
		}
		L('Удалён event '.$event_name);
		unset(self::$list[$event_name]);
		return true;
	}
	/**
	 * Проверка на существование евента
	 *
	 * @param string $name имя евента
	 * @return boolean
	 */
	public static function is_event($name){
		return isset(self::$list[$name]);
	}
	/**
	 * Ищем событие
	 *
	 * @param string $event_name имя события
	 * @param string $class_name класс для вызова
	 * @param string $function_name функция для вызова
	 * @return int идентификатор эвента или false
	 */
	private static function findEvent($event_name,$class_name=false,$function_name=false){
		foreach (self::$list[$event_name] as $key=>$item) {
			if($class_name && $item['class']!=$class_name)continue;
			if($function_name && $item['function']!=$function_name)continue;
			return $key+1;
		}
		return false;
	}
	/**
	 * Получаем информацию о евенте
	 *
	 * @param string $name имя события
	 */
	public static function info($name=false){
		if($name){
			if(!isset(self::$list[$name]))return false;
			pr(self::$list[$name]);
		}
		else pr(self::$list);
		return true;
	}
}